package com.apestech.api.workflow.lib.element;

import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author hup
 * @create 2018-07-04-10:39
 */
public class FlowBpmn {

    private WorkProcessEngine engine;
    private BpmnModel bpmnModel;
    private String processInstanceId;
    private String type;
    private ProcessInstance runtimeProcessInstance;
    private HistoricProcessInstance historicProcessInstance;
    private ProcessEngineConfiguration processEngineConfiguration;

    public FlowBpmn(WorkProcessEngine engine, String processInstanceId){
        init(engine, processInstanceId, null);
    }

    public FlowBpmn(WorkProcessEngine engine, String processInstanceId, String type){
        init(engine, processInstanceId, type);
    }

    private void init(WorkProcessEngine engine, String processInstanceId, String type){
        this.engine=engine;
        this.processInstanceId=processInstanceId;
        this.type=type;
    }

    public void getBpmn() throws Exception {
        runtimeProcessInstance = null;
        if("runtime".equals(type) || type==null){
            runtimeProcessInstance = engine.getRuntimeService().createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        }
        bpmnModel=null;
        if(runtimeProcessInstance != null){
            bpmnModel = engine.getRepositoryService().getBpmnModel(runtimeProcessInstance.getProcessDefinitionId());
            if(type==null){
                type="runtime";
            }
        }else if("history".equals(type) || type==null){
            historicProcessInstance = engine.getHistoryService().createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if(historicProcessInstance != null){
                bpmnModel = engine.getRepositoryService().getBpmnModel(historicProcessInstance.getProcessDefinitionId());
            }
            if(type==null){
                type="history";
            }
        }
    }

    public BpmnModel getBpmnModel() {
        return bpmnModel;
    }

    public String getProcessInstanceId() {
        return processInstanceId;
    }

    public String getType() {
        return type;
    }

    public ProcessInstance getRuntimeProcessInstance() {
        return runtimeProcessInstance;
    }

    public HistoricProcessInstance getHistoricProcessInstance() {
        return historicProcessInstance;
    }

    public InputStream getProcessInstancePng()throws Exception{
        InputStream imageStream = null;
        getBpmn();
        if(processEngineConfiguration==null){
            processEngineConfiguration = engine.getProcessEngineConfiguration();
        }
        if(runtimeProcessInstance != null){
            List<String> activeActivityIds = engine.getRuntimeService().getActiveActivityIds(processInstanceId);
            ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
            imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, Collections.<String>emptyList(),"宋体", "宋体", "宋体",null, 1.0);
        }else if(historicProcessInstance != null){
            List<HistoricActivityInstance> activityInstances = engine.getHistoryService().createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
            List<String> activeActivityIds = new ArrayList<String>(activityInstances.size());
            if (activityInstances!=null && !activityInstances.isEmpty()) {
                for (HistoricActivityInstance activityInstance : activityInstances) {
                    activeActivityIds.add(activityInstance.getActivityId());
                }
            }
            List<String> activeFlowsIds = new ArrayList<String>();
            for(FlowElement activity : bpmnModel.getMainProcess().getFlowElements()){
                if(activity instanceof FlowNode){
                    int index = activeActivityIds.indexOf(activity.getId());
                    if(index>=0 && index+1<activeActivityIds.size()){
                        List<SequenceFlow> outgoingFlows = ((FlowNode) activity).getOutgoingFlows();
                        for(SequenceFlow flow:outgoingFlows){
                            String destinationFlowId = flow.getTargetRef();
                            if(destinationFlowId.equals(activeActivityIds.get(index+1))){
                                activeFlowsIds.add(flow.getId());
                            }
                        }
                    }
                }
            }
            ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
            imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds, activeFlowsIds,"宋体", "宋体", "宋体",null,1.0);
        }
        return imageStream;
    }

}
